package ru.ssau.customerManagement.model;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import ru.ssau.customerManagement.model.entities.Customer;
import ru.ssau.customerManagement.model.entities.CustomerLocation;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.*;

/**
 * Author: illabefat
 * Time: 02.11.2014
 */

@XmlRootElement(name = "model")
@XmlAccessorType(XmlAccessType.FIELD)
public class ModelImpl implements Serializable, Model {
    private static final long serialVersionUID = 2334730043997165608L;

    private Map<Long, Customer> customers;
    private Map<Long, CustomerLocation> customerLocations;

    @XmlTransient
    private  Set<Long> lockedCustomers;
    @XmlTransient
    private  Set<Long> lockedCustomerLocations;

    public ModelImpl()
    {
        customers = new HashMap<Long, Customer>();
        customerLocations = new HashMap<Long, CustomerLocation>();
        lockedCustomerLocations = new HashSet<Long>();
        lockedCustomers = new HashSet<Long>();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        lockedCustomerLocations = new HashSet<Long>();
        lockedCustomers = new HashSet<Long>();
    }

    public Customer getCustomer(Long id)
    {
        return customers.get(id);
    }

    public CustomerLocation getCustomerLocation(Long id)
    {
        return customerLocations.get(id);
    }

    public List<CustomerLocation> getCustomerLocationsByCustomer(final Long customerId)
    {
        return Lists.newArrayList(Iterables.filter(customerLocations.values(), new Predicate<CustomerLocation>() {
            @Override
            public boolean apply(CustomerLocation customerLocation) {
                return customerId.equals(customerLocation.getCustomerId());
            }
        }));
    }

    public List<Customer> getCustomers()
    {
        return new ArrayList<Customer>(customers.values());
    }

    public void addCustomer(Customer customer)
    {
        customers.put(customer.getId(), customer);
    }

    public void addCustomerLocation(CustomerLocation location)
    {
        customerLocations.put(location.getId(), location);
    }

    public void changeCustomer(Customer newCustomer)
    {
        customers.put(newCustomer.getId(), newCustomer);
    }

    public void changeCustomerLocation(CustomerLocation location)
    {
        customerLocations.put(location.getId(), location);
    }

    public void removeCustomer(Long id)
    {
        customers.remove(id);
    }

    public void removeCustomerLocation(Long id)
    {
        customerLocations.remove(id);
    }

    public boolean isCustomerLocked(Long id)
    {
        return lockedCustomers.contains(id);
    }

    public synchronized boolean lockCustomer(Long id)
    {
        if (isCustomerLocked(id))
            return false;
        lockedCustomers.add(id);
        return true;
    }

    public void unlockCustomer(Long id)
    {
        lockedCustomers.remove(id);
    }

    public boolean isCustomerLocationLocked(Long id)
    {
        return lockedCustomerLocations.contains(id);
    }

    public synchronized boolean lockCustomerLocation(Long id)
    {
        if (isCustomerLocationLocked(id))
            return false;
        lockedCustomerLocations.add(id);
        return true;
    }

    public void unlockCustomerLocation(Long id)
    {
        lockedCustomerLocations.remove(id);
    }

    @Override
    public List<Customer> findCustomersByName(String name) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public List<CustomerLocation> findCustomerLocationsByAddress(String address) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public List<CustomerLocation> getAllLocations() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
